#include "scanner.h"
#include "db.h"
#include "utils.h"
#include <iostream>
#include <thread>
#include <getopt.h>
#include <unistd.h>
#include <limits.h>

using namespace FileScanner;

int main(int argc, char* argv[]) {
    std::string directory;
    std::string sizeStr = "100k";
    bool checkMode = false;
    bool queryMode = false;
    int workerCount = static_cast<int>(std::thread::hardware_concurrency() * 1.5);

    // 获取可执行文件所在目录作为数据库路径
    std::string dbPath;
    char result[PATH_MAX];
    ssize_t count = readlink("/proc/self/exe", result, PATH_MAX);
    if (count != -1) {
        result[count] = '\0';
        std::string exePath(result);
        size_t lastSlash = exePath.find_last_of("/");
        if (lastSlash != std::string::npos) {
            dbPath = exePath.substr(0, lastSlash + 1) + "filescanner.db";
        } else {
            dbPath = "./filescanner.db";
        }
    } else {
        dbPath = "./filescanner.db";
    }

    // 解析命令行参数
    int opt;
    struct option long_options[] = {
        {"directory", required_argument, 0, 'd'},
        {"size", required_argument, 0, 's'},
        {"workers", required_argument, 0, 'w'},
        {"check", no_argument, 0, 'c'},
        {"query", no_argument, 0, 'q'},
        {"help", no_argument, 0, 'h'},
        {0, 0, 0, 0}
    };

    while ((opt = getopt_long(argc, argv, "d:s:cqw:h", long_options, nullptr)) != -1) {
        switch (opt) {
            case 'd':
                directory = optarg;
                break;
            case 's':
                sizeStr = optarg;
                break;
            case 'c':
                checkMode = true;
                break;
            case 'q':
                queryMode = true;
                break;
            case 'w':
                try {
                    workerCount = std::stoi(optarg);
                    if (workerCount <= 0) {
                        logError("工作线程数必须大于 0");
                        return 1;
                    }
                } catch (const std::exception&) {
                    logError("无效的工作线程数: " + std::string(optarg));
                    return 1;
                }
                break;
            case 'h':
                showHelp();
                return 0;
            default:
                showHelp();
                return 1;
        }
    }

    // 检查参数
    if (!checkMode && !queryMode && directory.empty()) {
        std::cerr << "错误: 必须指定一个操作" << std::endl;
        std::cerr << "" << std::endl;
        std::cerr << "使用示例:" << std::endl;
        std::cerr << "  filescanner -d <目录> [-s <文件大小>] [-w <线程数>]  扫描目录文件" << std::endl;
        std::cerr << "  filescanner -c                                     检查数据库中的文件" << std::endl;
        std::cerr << "  filescanner -q                                     查询重复文件" << std::endl;
        std::cerr << "" << std::endl;
        std::cerr << "参数说明:" << std::endl;
        std::cerr << "  -d, --directory <DIR>  指定要扫描的目录" << std::endl;
        std::cerr << "  -s, --size <SIZE>      忽略小于指定大小的文件 (默认: 100k)" << std::endl;
        std::cerr << "  -w, --workers <NUM>    指定工作线程数 (默认: CPU核心数的1.5倍)" << std::endl;
        std::cerr << "  -c, --check            检查数据库中的文件是否存在" << std::endl;
        std::cerr << "  -q, --query            查询MD5相同的文件" << std::endl;
        std::cerr << "" << std::endl;
        std::cerr << "使用 --help 查看完整帮助信息" << std::endl;
        return 1;
    }

    // 解析文件大小
    long long minSize = parseFileSize(sizeStr);
    if (minSize < 0) {
        logError("无效的文件大小格式: " + sizeStr);
        return 1;
    }

    // 初始化数据库
    Database db(dbPath);
    if (!db.initialize()) {
        logError("数据库初始化失败");
        return 1;
    }

    try {
        if (checkMode) {
            // 检查模式
            std::cout << "开始检查数据库记录..." << std::endl;
            Scanner scanner("", 0, 1, db);
            scanner.checkIntegrity();
        } else if (queryMode) {
            // 查询重复文件模式
            std::cout << "查询重复文件..." << std::endl;
            auto duplicates = db.getDuplicateFiles();
            if (duplicates.empty()) {
                std::cout << "没有找到MD5相同的文件" << std::endl;
            } else {
                for (const auto& file : duplicates) {
                    std::cout << file.path << "|" << file.md5 << "|" << file.size << std::endl;
                }
            }
        } else {
            // 扫描模式
            Scanner scanner(directory, minSize, workerCount, db);
            scanner.scan();
        }
    } catch (const std::exception& e) {
        logError("程序执行出错: " + std::string(e.what()));
        return 1;
    }

    return 0;
}
